<template>
  <div class="operationBar">
    <div class="space"></div>

    <div class="label">分组:</div>
    <div class="space"></div>
    <div class="space"></div>
    <el-select
      v-model="currentGroupSelectValue"
      placeholder="Select"
      clearable
      style="width: 170px"
    >
      <el-option
        v-for="item in projectGroupOptions"
        :key="item.id"
        :label="item.name"
        :value="item.id"
      />
    </el-select>

    <div class="space"></div>
    <div class="space"></div>

    <el-dropdown trigger="hover" size="default" @command="handleCommand">
      <el-icon size="20" color="#9900ff" title="项目相关设置">
        <Tools />
      </el-icon>
      <template #dropdown>
        <el-dropdown-menu>
          <el-dropdown-item command="add">
            <el-icon size="18" color="#95d475"><CirclePlusFilled /></el-icon>
            <span style="margin-left: 10px">新建项目分组</span>
          </el-dropdown-item>
          <el-dropdown-item command="modify">
            <el-icon size="18" color="#eebe77"><Edit /></el-icon>
            <span style="margin-left: 10px">修改当前分组</span>
          </el-dropdown-item>
          <el-dropdown-item command="deleteGroup">
            <el-icon size="18" color="#fab6b6"><DeleteFilled /></el-icon>
            <span style="margin-left: 10px">删除当前分组</span>
          </el-dropdown-item>
          <el-dropdown-item command="recycle" divided>
            <el-icon size="18" color="#eebe77"><LocationFilled /></el-icon>
            <span style="margin-left: 10px">前往回收站</span>
          </el-dropdown-item>
          <el-dropdown-item command="updateProject" divided>
            <el-icon size="18" color="#eebe77"><Edit /></el-icon>
            <span style="margin-left: 10px">修改当前项目</span>
          </el-dropdown-item>
          <el-dropdown-item command="deleteProject">
            <el-icon size="18" color="#F56C6C"><DeleteFilled /></el-icon>
            <span style="margin-left: 10px">删除当前项目</span>
          </el-dropdown-item>
        </el-dropdown-menu>
      </template>
    </el-dropdown>

    <div class="space"></div>
    <div class="space"></div>
    <el-icon
      v-show="currentGroupDesc"
      :title="'分组描述：' + currentGroupDesc"
      color="#eebe77"
      size="20"
    >
      <InfoFilled />
    </el-icon>

    <div class="uploadBtn">
      <div @click="() => (uploadModal = true)">
        <i class="icon-upload-cloud-line"></i>
      </div>
    </div>
  </div>

  <!-- 图片列表  -->
  <div id="imageList" class="imageList">
    <!-- 瀑布流布局组件 -->
    <Waterfall
      :list="(currentResourceList as any)"
      :width="110"
      :animationDelay="160"
      :breakpoints="{
        890: { rowPerView: 7 },
        780: { rowPerView: 6 },
        670: { rowPerView: 5 },
        560: { rowPerView: 4 },
        450: { rowPerView: 3 },
      }"
    >
      <template #item="{ item, index }">
        <ImageItem
          :key="item.id"
          :id="item.id"
          :serial="index"
          :path="item.path"
          :time="item.createTime"
          :refreshList="() => getResources(true)"
          :previewSrcList="previewSrcList"
        />
      </template>
    </Waterfall>
  </div>

  <!--  -->
  <!-- 新增项目分组对话框 -->
  <el-dialog
    v-model="addGroupDialogVisible"
    title="新建项目分组对话框"
    width="390"
    :before-close="handleDialogClose"
  >
    <div style="display: flex; align-items: center; padding-bottom: 6px">
      <div style="font-size: 16px; font-weight: bold; color: #909090">
        分组名称：
      </div>
      <el-input
        v-model="groupName"
        style="width: 260px"
        placeholder="Please input"
      />
    </div>
    <div style="display: flex; align-items: center">
      <div style="font-size: 16px; font-weight: bold; color: #909090">
        分组描述：
      </div>
      <el-input
        v-model="groupDesc"
        style="width: 260px"
        placeholder="Please input"
        :rows="3"
        type="textarea"
      />
    </div>

    <template #footer>
      <div>
        <el-button @click="handleDialogClose">Cancel</el-button>
        <el-button type="primary" @click="addProjectGroup">创建</el-button>
      </div>
    </template>
  </el-dialog>

  <!--  -->
  <!-- 更新项目分组对话框 -->
  <el-dialog
    v-model="updateGroupDialogVisible"
    title="更新项目分组对话框"
    width="390"
    :before-close="handleDialogClose"
  >
    <div style="display: flex; align-items: center; padding-bottom: 6px">
      <div style="font-size: 16px; font-weight: bold; color: #909090">
        分组名称：
      </div>
      <el-input
        v-model="groupName"
        style="width: 260px"
        placeholder="Please input"
      />
    </div>
    <div style="display: flex; align-items: center">
      <div style="font-size: 16px; font-weight: bold; color: #909090">
        分组描述：
      </div>
      <el-input
        v-model="groupDesc"
        style="width: 260px"
        placeholder="Please input"
        :rows="3"
        type="textarea"
      />
    </div>

    <template #footer>
      <div>
        <el-button @click="handleDialogClose">Cancel</el-button>
        <el-button type="primary" @click="updateProjectGroup">更新</el-button>
      </div>
    </template>
  </el-dialog>

  <!--  -->
  <!-- 删除项目分组对话框 -->
  <el-dialog
    v-model="deleteGroupDialogVisible"
    title="删除项目分组对话框"
    width="280"
    :before-close="handleDialogClose"
  >
    <div style="font-size: 16px; font-weight: bold; color: #909090">
      确认删除当前分组？分组中的图片也会一并删除
    </div>

    <template #footer>
      <div>
        <el-button @click="handleDialogClose">Cancel</el-button>
        <el-button type="danger" @click="deleteProjectGroup"> 删除 </el-button>
      </div>
    </template>
  </el-dialog>

  <!--  -->
  <!-- 更新项目对话框 -->
  <el-dialog
    v-model="updateProjectDialogVisible"
    title="更新项目对话框"
    width="390"
    :before-close="handleDialogClose"
  >
    <div style="display: flex; align-items: center; padding-bottom: 6px">
      <div style="font-size: 16px; font-weight: bold; color: #909090">
        项目名称：
      </div>
      <el-input
        v-model="projectName"
        style="width: 260px"
        placeholder="Please input"
      />
    </div>
    <div style="display: flex; align-items: center">
      <div style="font-size: 16px; font-weight: bold; color: #909090">
        项目描述：
      </div>
      <el-input
        v-model="projectDesc"
        style="width: 260px"
        placeholder="Please input"
        :rows="3"
        type="textarea"
      />
    </div>

    <template #footer>
      <div>
        <el-button @click="handleDialogClose">Cancel</el-button>
        <el-button type="primary" @click="updateProjectGroupHandle">
          更新
        </el-button>
      </div>
    </template>
  </el-dialog>

  <!--  -->
  <!-- 删除项目对话框 -->
  <el-dialog
    v-model="deleteProjectDialogVisible"
    title="删除项目对话框"
    width="280"
    :before-close="handleDialogClose"
  >
    <div style="font-size: 16px; font-weight: bold; color: #909090">
      确认删除当前项目？项目中的所有图片也会一并删除
    </div>

    <template #footer>
      <div>
        <el-button @click="handleDialogClose">Cancel</el-button>
        <el-button type="danger" @click="deleteProjectHandle"> 删除 </el-button>
      </div>
    </template>
  </el-dialog>

  <!-- 上传图片对话框 -->
  <UploadModal
    :visible="uploadModal"
    :refresh="() => getResources(true)"
    :close="closeUploadModal"
    :projectId="currentProjectId"
    :projectGroupId="currentGroupSelectValue"
  />
</template>

<script lang="tsx" setup>
import { ref, computed, onMounted, watch, defineComponent } from 'vue'
import { useRouter } from 'vue-router'
import {
  Tools,
  CirclePlusFilled,
  DeleteFilled,
  Edit,
  UploadFilled,
  Download,
  Clock,
  DocumentCopy,
  InfoFilled,
  LocationFilled,
} from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import 'element-plus/theme-chalk/el-message.css'
import { storeToRefs } from 'pinia'
import { Waterfall } from 'vue-waterfall-plugin-next'
import 'vue-waterfall-plugin-next/dist/style.css'
import styles from './home.module.less'
import { useProjectStore } from '@/features/store/store'
import {
  addProjectGroupApi,
  updateProjectGroupApi,
  deleteProjectGroupApi,
  getProjectGroupApi,
} from '@/request/api/projectGroup'
import {
  uploadResourcesApi,
  deleteResourcesApi,
  getResourcesApi,
} from '@/request/api/resource'
import { fetchOriginFile } from '@/utils/func'
import { throttle } from '@/utils/func'

const router = useRouter()
// 路由跳转
const navigateTo = (path: string) => router.push(path)

const { currentProjectId, currentProjectName, currentProjectDesc } =
  storeToRefs(useProjectStore())
const { deleteProject, updateProject } = useProjectStore()

onMounted(() => {
  getProjectGroup()
})

// 项目分组列表
const projectGroupOptions = ref<ProjectGroupItf[]>([])
// 当前选择的项目分组
const currentGroupSelectValue = ref<string>('')

// 当前选择的项目分组名称
const currentGroupName = computed(() => {
  const l = projectGroupOptions.value.filter(
    (item) => item.id === currentGroupSelectValue.value
  )
  if (l.length === 0) return ''
  else return l[0]?.name
})
// 当前选择的项目分组描述
const currentGroupDesc = computed(() => {
  const l = projectGroupOptions.value.filter(
    (item) => item.id === currentGroupSelectValue.value
  )
  if (l.length === 0) return ''
  else return l[0]?.description
})

// 获取项目分组
const getProjectGroup = async () => {
  if (currentProjectId.value === '') return
  const res = await getProjectGroupApi(currentProjectId.value)
  if (res.code !== 200) return ElMessage.error('获取项目分组失败')
  projectGroupOptions.value = res.data
}

//
//
// 下拉菜单点击回调
const handleCommand = (command: string | number) => {
  const openGroupUpdateDialog = () => {
    if (currentGroupSelectValue.value.length === 0)
      return ElMessage.warning('请选择一个分组')

    groupName.value = currentGroupName.value
    groupDesc.value = currentGroupDesc.value
    updateGroupDialogVisible.value = true
  }

  const openGroupDeleteDialog = () => {
    if (currentGroupSelectValue.value.length === 0)
      return ElMessage.warning('请选择一个分组')
    deleteGroupDialogVisible.value = true
  }

  const openProjectUpdateDialog = () => {
    projectDesc.value = currentProjectDesc.value
    projectName.value = currentProjectName.value
    updateProjectDialogVisible.value = true
  }

  const optionFunc: { [key: string | number]: Function } = {
    add: () => (addGroupDialogVisible.value = true),
    modify: () => openGroupUpdateDialog(),
    deleteGroup: () => openGroupDeleteDialog(),
    recycle: () => navigateTo('/recycle'),
    deleteProject: () => (deleteProjectDialogVisible.value = true),
    updateProject: () => openProjectUpdateDialog(),
  }

  optionFunc[command]()
}

//
//
// 项目分组的一些参数
const groupName = ref<string>('')
const groupDesc = ref<string>('')
const addGroupDialogVisible = ref<boolean>(false)
const updateGroupDialogVisible = ref<boolean>(false)
const deleteGroupDialogVisible = ref<boolean>(false)

// 项目的一些参数
const projectName = ref<string>('')
const projectDesc = ref<string>('')
const updateProjectDialogVisible = ref<boolean>(false)
const deleteProjectDialogVisible = ref<boolean>(false)

const handleDialogClose = () => {
  addGroupDialogVisible.value = false
  updateGroupDialogVisible.value = false
  deleteGroupDialogVisible.value = false
  updateProjectDialogVisible.value = false
  deleteProjectDialogVisible.value = false
  groupName.value = ''
  groupDesc.value = ''
  projectName.value = ''
  projectDesc.value = ''
}

// 新增项目分组
const addProjectGroup = async () => {
  if (groupName.value.trim().length === 0)
    return ElMessage.error('项目分组名称不能为空')

  const res = await addProjectGroupApi(
    groupName.value,
    groupDesc.value,
    currentProjectId.value
  )
  if (res.code !== 200) return ElMessage.error('添加项目分组失败')
  ElMessage.success('添加项目分组成功')
  getProjectGroup()
  handleDialogClose()
}

// 更新项目分组
const updateProjectGroup = async () => {
  if (groupName.value.trim().length === 0)
    return ElMessage.error('项目分组名称不能为空')

  const res = await updateProjectGroupApi(
    currentGroupSelectValue.value,
    groupName.value,
    groupDesc.value
  )
  if (res.code !== 200) return ElMessage.error('更新项目分组失败')
  ElMessage.success('更新项目分组成功')
  getProjectGroup()
  handleDialogClose()
}

// 删除项目分组
const deleteProjectGroup = async () => {
  const res = await deleteProjectGroupApi(currentGroupSelectValue.value)
  if (res.code !== 200) return ElMessage.error('删除项目分组失败')
  ElMessage.success('删除项目分组成功')
  currentGroupSelectValue.value = ''
  getProjectGroup()
  getProjectGroup()
  handleDialogClose()
}

// 修改当前项目信息
const updateProjectGroupHandle = () => {
  const res = updateProject(projectName.value, projectDesc.value)
  updateProjectDialogVisible.value = false
  if (res) ElMessage.success('更新成功')
  else ElMessage.error('更新失败')
}

// 删除当前项目
const deleteProjectHandle = () => {
  const res = deleteProject()
  deleteProjectDialogVisible.value = false
  if (res) ElMessage.success('删除成功')
  else ElMessage.error('删除失败')
}

//
// 上传文件对话框
const uploadModal = ref<boolean>(false)
const closeUploadModal = () => (uploadModal.value = false)

//
//
// 上传图片对话框组件
const UploadModal = defineComponent({
  props: {
    visible: { type: Boolean, default: false },
    refresh: { type: Function, default: () => '' },
    close: { type: Function, default: () => '' },
    projectId: { type: String, default: '' },
    projectGroupId: { type: String, default: '' },
  },
  setup(props) {
    watch(
      () => props.visible,
      (val) => {
        uploadModal.value = val
        if (val) return
        uploadImagesMap.clear()
        uploadList.value = []
      }
    )

    // 上传文件对话框
    const uploadModal = ref<boolean>(false)
    // 上传的文件列表
    let uploadImagesMap = new Map()
    // 上传的文件列表
    const uploadList = ref<any[]>([])

    // 上传文件之前
    const beforeUploadHandler = () => false
    // 文件变化回调
    const onChangeHandler = (info) => {
      if (!info) return
      uploadImagesMap.set(info.uid, info.raw)
      uploadList.value = [...uploadImagesMap.values()]
    }
    // 文件移除回调
    const onRemoveHandler = (info) => {
      uploadImagesMap.delete(info.uid)
      uploadList.value = [...uploadImagesMap.values()]
    }

    // 批量上传图片
    const uploadResources = async () => {
      if (uploadList.value.length === 0) return ElMessage.warning('列表为空！')

      let formdata = new FormData()
      const arr = [...uploadImagesMap.values()]
      arr.reduce((accumulator, item) => {
        accumulator.append('resources', fetchOriginFile(item))
        return accumulator // 返回累加器
      }, formdata)

      const res = await uploadResourcesApi(
        formdata,
        props.projectId,
        props.projectGroupId
      )

      if (res.code !== 200) return ElMessage.error('上传失败！')
      ElMessage.success('上传成功！')
      uploadImagesMap.clear()
      uploadList.value = []
      props.refresh()
    }

    return () => (
      <>
        <el-dialog
          model-value={uploadModal.value}
          title="上传图片"
          width="90%"
          style={{ 'max-width': '600px' }}
          onClose={props.close}
        >
          <el-upload
            drag
            multiple
            limit={15}
            disabled={uploadList.value.length >= 15 ? true : false}
            auto-upload={false}
            file-list={uploadList.value}
            before-upload={beforeUploadHandler}
            on-change={onChangeHandler}
            on-remove={onRemoveHandler}
          >
            <el-icon class="el-icon--upload">
              <UploadFilled />
            </el-icon>
            <div class="el-upload__text">
              Drop file here or <em>click to upload</em>
              <div class="el-upload__tip">可拖拽进行上传</div>
              <div class="el-upload__tip">最大上传数量为15</div>
            </div>
          </el-upload>
          <div
            style={{
              display: 'flex',
              justifyContent: 'center',
              width: '100%',
              marginTop: '20px',
            }}
          >
            <el-button type="primary" onClick={uploadResources}>
              上传 ({uploadList.value.length})
            </el-button>
          </div>
        </el-dialog>
      </>
    )
  },
})

//
// 分页栏相关变量
const page = ref(1)
const pageSize = ref(20)
const total = ref(0)
const setPage = (val: number) => (page.value = val)
// const setPageSize = (val: number) => (pageSize.value = val)

const currentResourceList = ref<ResourceItf[]>([])
// 预览的资源地址
const previewSrcList = ref<string[]>([])

//分页获取资源列表
const getResources = async (refresh: boolean = false) => {
  if (!currentProjectId.value) return
  if (refresh) {
    currentResourceList.value = []
    previewSrcList.value = []
    page.value = 1
  }

  const res = await getResourcesApi(
    pageSize.value,
    page.value,
    currentProjectId.value,
    currentGroupSelectValue.value
  )
  if (res.code !== 200) return ElMessage.error('获取资源列表失败')
  currentResourceList.value = [
    ...currentResourceList.value,
    ...res.data.records,
  ]
  total.value = res.data.total
  // ElMessage.success('获取资源列表成功')
  let pl = []
  res.data.records.filter((item) => pl.push(item.path))
  previewSrcList.value = [...previewSrcList.value, ...pl]
}

// 节流函数
const throttleFunc = throttle(() => setPage(page.value + 1), 1000)
// 列表滚动自动加载
const initscroll = () => {
  let block = document.getElementById('imageList')
  block.addEventListener('scroll', () => {
    if (block.scrollTop > block.scrollHeight * 0.6) {
      if (currentResourceList.value.length >= total.value) return
      // const p = page.value + 1
      // setPage(p)
      throttleFunc()
    }
  })
}

onMounted(() => {
  getResources()
  initscroll()
})

watch(
  () => currentProjectId.value,
  () => {
    if (currentProjectId.value === '') return
    currentGroupSelectValue.value = ''
    projectGroupOptions.value = []
    getProjectGroup()
    getResources(true)
  }
)
watch(
  () => currentGroupSelectValue.value,
  () => getResources(true)
)
watch(
  () => page.value,
  () => getResources()
)
watch(
  () => pageSize.value,
  () => getResources()
)

//
//
// 图片项组件
const ImageItem = defineComponent({
  props: {
    id: { type: String, default: '' },
    path: { type: String, default: '' },
    time: { type: String, default: '' },
    serial: { type: Number, default: 0 },
    refreshList: { type: Function, default: null },
    previewSrcList: { type: Array, default: [] },
  },
  setup(props) {
    const myElementRef = ref<any>()
    const show = ref<boolean>(false)

    onMounted(() => {
      const element = myElementRef.value

      if (!element) return
      element.addEventListener('mouseenter', () => {
        show.value = true
      })
      element.addEventListener('mouseleave', () => {
        show.value = false
      })
    })

    // 复制图片路径
    const copyText = () => {
      navigator.clipboard
        .writeText(props.path)
        .then(() => ElMessage.success('复制地址成功'))
        .catch(() => ElMessage.error('复制地址失败'))
    }

    // 下载文件
    const downFile = () => (window as any).fileControll.downFile(props.path)

    // 删除图片
    const deleteResources = async () => {
      const res = await deleteResourcesApi([props.id])
      if (res.code !== 200) return ElMessage.error('删除失败！')
      ElMessage.success('删除成功！')
      props.refreshList()
    }

    return () => (
      <div class={styles.imageItem} ref={myElementRef}>
        <div style="display:flex;justify-content: center">
          <el-image
            style="width: 90px; "
            src={props.path}
            fit="fill"
            preview-src-list={props.previewSrcList}
            preview-teleported={true}
            initial-index={props.serial}
            infinite={false}
            hide-on-click-modal={true}
          />
        </div>

        <div class={styles.serial}>{props.serial + 1}</div>

        {show.value ? (
          <div class={styles.btn}>
            <el-icon title="下载图片" onClick={downFile}>
              <Download />
            </el-icon>
            <el-icon title={`上传时间：${props.time}`}>
              <Clock />
            </el-icon>
            <el-icon title="复制图片地址" onClick={copyText}>
              <DocumentCopy />
            </el-icon>
          </div>
        ) : (
          <div class={styles.btn}></div>
        )}

        {show.value ? (
          <el-icon
            class={styles.deleteBtn}
            title="删除"
            onClick={deleteResources}
          >
            <DeleteFilled />
          </el-icon>
        ) : (
          ''
        )}
      </div>
    )
  },
})
</script>

<style lang="less" scoped>
.space {
  width: 5px;
  height: 5px;
}

.operationBar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  padding: 5px;
  height: 32px;
  background-color: rgba(175, 160, 245, 0.2);

  > .label {
    font-weight: bold;
    color: #606266;
    display: flex;
    align-items: center;
    letter-spacing: 2px;
  }
  > .uploadBtn {
    flex: 1;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    height: 100%;

    > div {
      background-color: #9f1cf7;
      color: white;
      height: 84%;
      width: 50px;
      border-radius: 6px;
      display: flex;
      align-items: center;
      justify-content: center;
      > i {
        font-size: 24px;
      }
    }
  }
}

.imageList {
  min-height: calc(100% - 42px);
  max-height: calc(100% - 42px);
  overflow: auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
  align-items: center;
  align-content: flex-start;
}
</style>
